﻿using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using Lilium.Web.Mvc.Context;
using Lilium.Web.Mvc.EntityFilters;
using Lilium.Web.Mvc.State;
using System.Linq.Expressions;

namespace Lilium.Web.Mvc.Html
{
    public static class EntityFilterExtensions
    {
        public static MvcHtmlString FilterActionLink(this HtmlHelper html, string linkText, IEntityFilter filter, string action)
        {
            var routeValues = GetRouteValues<ControllerBase>(html, filter, action, null, false);

            return System.Web.Mvc.Html.LinkExtensions.RouteLink(html, linkText, routeValues);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="html"></param>
        /// <param name="filter"></param>
        /// <param name="filterAction"></param>
        /// <returns></returns>
        /// <remarks>
        /// Автоматически исключает состояние текущего фильтра из GET строки, чтобы нормально подменять
        /// параметры с помощью формы.
        /// </remarks>
        public static MvcForm BeginFilterForm(
            this HtmlHelper html,
            IEntityFilter filter,
            string filterAction)
        {
            var routeValues = GetRouteValues<ControllerBase>(html, filter, filterAction, null, true);

            return System.Web.Mvc.Html.FormExtensions.BeginForm(html, routeValues);
        }

        public static MvcForm BeginFilterForm(
            this HtmlHelper html,
            IEntityFilter filter,
            string filterAction,
            RouteValueDictionary routeValues)
        {
            if (html == null) throw new ArgumentNullException("html");
            if (filter == null) throw new ArgumentNullException("filter");

            var statefullObject = filter as IStatefulObject;
            if (statefullObject != null)
            {
                var stateService = html.GetService<IStateService>(true);
                stateService.SaveObjectState(statefullObject, filterAction, routeValues);
            }

            return System.Web.Mvc.Html.FormExtensions.BeginForm(html, routeValues);
        }

        public static MvcForm BeginFilterForm<TController>(
            this HtmlHelper html,
            IEntityFilter filter,
            string filterAction,
            Expression<Func<TController, ActionResult>> action)
        {
            var routeValues = GetRouteValues(html, filter, filterAction, action, true);

            return System.Web.Mvc.Html.FormExtensions.BeginForm(html, routeValues);
        }

        private static RouteValueDictionary GetRouteValues<TController>(
            HtmlHelper html,
            IEntityFilter filter,
            string filterAction,
            Expression<Func<TController, ActionResult>> action,
            bool excludeFilterState)
        {
            if (html == null) throw new ArgumentNullException("html");
            if (filter == null) throw new ArgumentNullException("filter");

            var routeValues = html.ViewContext.Controller.GetCombinedRouteValuesWithState(action, null); 

            var statefullObject = filter as IStatefulObject;
            if (statefullObject != null)
            {
                if (excludeFilterState)
                {
                    routeValues.Remove(statefullObject.Key);
                }
                else
                {
                    var stateService = html.GetService<IStateService>(true);
                    stateService.SaveObjectState(statefullObject, filterAction, routeValues);
                }
            }
            return routeValues;
        }
    }
}